package com.astrocsr.business;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.astrocsr.common.Constants;
import com.astrocsr.domain.bean.TblGroup;
import com.astrocsr.domain.bean.TblModule;
import com.astrocsr.domain.bean.TblPermission;
import com.astrocsr.domain.condition.SecCondition;
import com.astrocsr.domain.db.PagingInfo;
import com.astrocsr.domain.db.SearchResult;
import com.astrocsr.domain.web.GroupInfo;
import com.astrocsr.domain.web.ModuleInfo;
import com.astrocsr.domain.web.PermissionInfo;
import com.astrocsr.domain.web.SecurityListingInfo;

@Service("securityListManager")
@Transactional(value = "transactionManager", propagation = Propagation.REQUIRED)
public class SecurityListManager extends BaseManager {

	/**
	 * Get All Security Listing Information
	 */
	public List<SecurityListingInfo> listSecurityListing() throws Exception {

		List<SecurityListingInfo> securityListingInfoList = null;

		return securityListingInfoList;
	}

	public void addModule(ModuleInfo moduleInfo) throws Exception {

		if (moduleInfo != null) {

			// Declare bean object
			TblModule tblModule = new TblModule();
			tblModule.setMerName(Constants.MERCHANT);
			tblModule.setModuleCode(moduleInfo.getModuleCode());
			tblModule.setModuleName(moduleInfo.getModuleName());
			tblModule.setCreateBy(moduleInfo.getCreatedBy());
			tblModule.setCreatedDate(new Date());
			tblModule.setModuleUri(moduleInfo.getModuleUri());
			tblModule.setOrderBy(moduleInfo.getOrderBy());
			tblModule.setParent(moduleInfo.getParent());
			
			// Call DAO layer to insert Database
			getModuleDAO().addModule(tblModule);
		}

	}

	public List<ModuleInfo> listModule() throws Exception {

		List<ModuleInfo> moduleInfoList = null;
		ModuleInfo moduleInfo = null;

		List<TblModule> moduleList = getModuleDAO().listModule();

		TblModule tblModule = null;

		if (moduleList != null && moduleList.size() > 0) {
			moduleInfoList = new ArrayList<ModuleInfo>();
			for (int i = 0; i < moduleList.size(); i++) {

				tblModule = moduleList.get(i);

				// copy fields to display
				moduleInfo = new ModuleInfo();
				moduleInfo.setModuleCode(tblModule.getModuleCode());
				moduleInfo.setModuleName(tblModule.getModuleName());
				moduleInfo.setModuleUri(tblModule.getModuleUri());
				moduleInfo.setOrderBy(tblModule.getOrderBy());
				moduleInfo.setParent(tblModule.getParent());

				moduleInfoList.add(moduleInfo);
			}
		}
		return moduleInfoList;
	}

	public List<ModuleInfo> listModuleParent() throws Exception {

		List<ModuleInfo> moduleInfoList = null;
		ModuleInfo moduleInfo = null;

		List<TblModule> moduleList = getModuleDAO().listParent();

		TblModule tblModule = null;

		if (moduleList != null && moduleList.size() > 0) {
			moduleInfoList = new ArrayList<ModuleInfo>();
			for (int i = 0; i < moduleList.size(); i++) {

				tblModule = moduleList.get(i);

				// copy fields to display
				moduleInfo = new ModuleInfo();
				moduleInfo.setModuleCode(tblModule.getModuleCode());
				moduleInfo.setModuleName(tblModule.getModuleName());
				moduleInfo.setModuleUri(tblModule.getModuleUri());
				moduleInfo.setOrderBy(tblModule.getOrderBy());
				moduleInfo.setParent(tblModule.getParent());

				moduleInfoList.add(moduleInfo);
			}
		}
		return moduleInfoList;
	}

	public void deleteModule(String moduleCode) throws Exception {

		if (StringUtils.isNotBlank(moduleCode)) {
			// Call DAO layer to insert Database
			getModuleDAO().deleteModule(moduleCode);
		}
	}

	public void deletePermission(String moduleCode,String groupCode)
			throws Exception {

		if (moduleCode != null) {
			// Call DAO layer to insert Database
			getPermissionDAO().deletePermission(moduleCode, groupCode);
		}
	}

	public List<PermissionInfo> listPermission(String groupCode)
			throws Exception {

		List<PermissionInfo> permissionInfoList = null;
		PermissionInfo permissionInfo = null;

		List<TblPermission> permissionList = getPermissionDAO()
				.listPermission(groupCode);

		TblPermission tblPermission = null;

		if (permissionList != null && permissionList.size() > 0) {
			permissionInfoList = new ArrayList<PermissionInfo>();
			for (int i = 0; i < permissionList.size(); i++) {
				tblPermission = permissionList.get(i);

				// copy fields to display
				permissionInfo = new PermissionInfo();
				permissionInfo.setMerName(tblPermission.getMerName());
				permissionInfo.setGroupCode(tblPermission.getGroupCode());
				permissionInfo.setModuleCode(tblPermission.getModuleCode());
				permissionInfo.setReadFlag(tblPermission.getReadFlag());
				permissionInfo.setUpdateFlag(tblPermission.getUpdateFlag());
				permissionInfo.setWriteFlag(tblPermission.getWriteFlag());
				permissionInfo.setCreatedBy(tblPermission.getCreatedBy());
				permissionInfo.setCreatedDate(tblPermission.getCreatedDate());
				permissionInfo.setModuleName(tblPermission.getModuleName());
				permissionInfoList.add(permissionInfo);
			}
		}
		return permissionInfoList;
	}

	/**
	 * List the modules that have not assigned to group
	 */
	public List<ModuleInfo> listRemainModule(String groupCode)
			throws Exception {

		List<ModuleInfo> moduleInfoList = null;
		ModuleInfo moduleInfo = null;

		List<TblModule> moduleList = getModuleDAO().listModule();
		List<TblPermission> permissionList = getPermissionDAO().listPermission(groupCode);
		
		TblModule 		tblModule 	  = null;
		TblPermission	tblPermission = null;
		if (moduleList != null && moduleList.size() > 0) {
			moduleInfoList = new ArrayList<ModuleInfo>(); 
			for (int i = 0; i < moduleList.size(); i++) {
				tblModule = moduleList.get(i);
				boolean isExisted = false;
				if (permissionList != null && permissionList.size() > 0) {
					for (int j = 0; j < permissionList.size(); j++) {
						
						tblPermission = permissionList.get(j);
						if (tblModule.getModuleCode().equals(tblPermission.getModuleCode())) {
							isExisted = true;
							break;
						}
					}
				}
				
				if (!isExisted) {
					// add remain module to return list
					moduleInfo = new ModuleInfo();
					BeanUtils.copyProperties(tblModule, moduleInfo);
					moduleInfoList.add(moduleInfo);
				}
			}
		}
		return moduleInfoList;
	}

	public void addPermission(PermissionInfo permissionInfo)
			throws Exception {

		if (permissionInfo != null
				&& !StringUtils.isEmpty(permissionInfo.getModuleCode())) {

			// Declare bean object
			TblPermission tblPermission = new TblPermission();
			tblPermission.setMerName(Constants.MERCHANT);
			tblPermission.setGroupCode(permissionInfo.getGroupCode());
			tblPermission.setModuleCode(permissionInfo.getModuleCode());
			tblPermission.setReadFlag(Constants.ReadFlag);
			tblPermission.setUpdateFlag(Constants.UpdateFlag);
			tblPermission.setWriteFlag(Constants.WriteFlag);
			tblPermission.setCreatedBy(permissionInfo.getCreatedBy());
			tblPermission.setCreatedDate(new Date());

			// Call DAO layer to insert Database
			getPermissionDAO().addPermission(tblPermission);
		}
	}

	public List<ModuleInfo> listModuleByRole(String roleCode)
			throws Exception {

		List<ModuleInfo> moduleInfoList 	= null;
		List<ModuleInfo> moduleInfoListLv2  = null;
		
		ModuleInfo moduleInfo = null;

		List<TblModule> moduleList = getModuleDAO().listModuleByRole(roleCode);

		TblModule tblModule = null;

		if (moduleList != null && moduleList.size() > 0) {
			moduleInfoList	 	= new ArrayList<ModuleInfo>();
			moduleInfoListLv2	= new ArrayList<ModuleInfo>();
			for (int i = 0; i < moduleList.size(); i++) {
				tblModule = moduleList.get(i);

				// copy fields to display
				moduleInfo = new ModuleInfo();
				BeanUtils.copyProperties(tblModule, moduleInfo);
				
				if (StringUtils.isBlank(moduleInfo.getParent())) {
					moduleInfoList.add(moduleInfo);
				} else {
					moduleInfoListLv2.add(moduleInfo);
				}
			}
			
			// set hierarchy
			for (ModuleInfo moduleInfoLv1 : moduleInfoList) {
				List<ModuleInfo> amTmpList = null;
				if (moduleInfoListLv2 != null && moduleInfoListLv2.size() > 0) {
					amTmpList = new ArrayList<ModuleInfo>();
					
					for (ModuleInfo moduleInfoLv2 : moduleInfoListLv2) {
						if (StringUtils.isNotBlank(moduleInfoLv1.getModuleCode()) 
								&& moduleInfoLv1.getModuleCode().equalsIgnoreCase(moduleInfoLv2.getParent())) {
							
							amTmpList.add(moduleInfoLv2);
						}
					}
				}
				moduleInfoLv1.setModuleInfoList(amTmpList);
			}
		}
		return moduleInfoList;
	}

	public String getModuleCode(String mPara) throws Exception { 
		  
		String listModuleCode = null; 

		TblModule tblModule = getModuleDAO().getModuleCode(mPara);

		if (tblModule != null) {   
			System.out.println("******* accessmodule = "  + tblModule.getModuleCode());
			
			listModuleCode = tblModule.getModuleCode();
		}
		return listModuleCode;
	}

	public List<GroupInfo> listGroupHierarchy(String startGroupCode) throws Exception {

		List<GroupInfo> infoList = null;
		GroupInfo info = null;

		List<TblGroup> beanList = getGroupDAO().listGroupHierarchy(startGroupCode);

		TblGroup bean = null;

		if (beanList != null && beanList.size() > 0) {
			infoList = new ArrayList<GroupInfo>();
			for (int i = 0; i < beanList.size(); i++) {

				bean = beanList.get(i);

				// copy fields to display
				info = new GroupInfo();
				BeanUtils.copyProperties(bean, info);
				infoList.add(info);
			}
		}
		return infoList;
	}

	/**
	 * List Groups by Parent Group
	 */
	public SearchResult<GroupInfo> listGroupByParentCode(String parentCode) throws Exception {
		return listGroupByParentCode(parentCode, null, null, false);
	}
	
	/**
	 * List Group by Parent Group with Paging
	 */
	public SearchResult<GroupInfo> listGroupByParentCode(String parentCode, GroupInfo groupInfo, PagingInfo pagingInfo) throws Exception {
		return listGroupByParentCode(parentCode, groupInfo, pagingInfo, false);
	}

	/**
	 * List Group by Parent Group with Paging and include parent or not
	 */
	public SearchResult<GroupInfo> listGroupByParentCode(String parentCode, GroupInfo groupInfo, PagingInfo pagingInfo, boolean withParent) throws Exception {

		SearchResult<GroupInfo> infoList = null;
		GroupInfo info = null;

		// prepare condition
		SecCondition condition = new SecCondition(parentCode);
		if (groupInfo != null) {
			condition.setGroupCode(groupInfo.getGroupCode());
			condition.setGroupName(groupInfo.getGroupName());
		}
		
		SearchResult<TblGroup> beanList = getGroupDAO().listGroupByParentCode(condition, pagingInfo, withParent);

		TblGroup bean = null;

		if (beanList != null && beanList.size() > 0) {
			infoList = new SearchResult<GroupInfo>();
			for (int i = 0; i < beanList.size(); i++) {

				bean = beanList.get(i);

				// copy fields to display
				info = new GroupInfo();
				BeanUtils.copyProperties(bean, info);
				infoList.add(info);
			}
		}
		return infoList;
	}
	
	public boolean checkExistingGroupCode(String groupCode) throws Exception { 

		TblGroup tblGroup = getGroupDAO().findByGroupCode(groupCode);

		if (tblGroup != null && StringUtils.isNotBlank(tblGroup.getGroupCode())) {   
			return true;
		}
		return false;
	}
	
	public void addGroup(GroupInfo groupInfo) throws Exception {

		if (groupInfo != null) {

			// Declare bean object
			TblGroup bean = new TblGroup();
			bean.setGroupCode(groupInfo.getGroupCode());
			bean.setGroupName(groupInfo.getGroupName());
			bean.setCreatedBy(groupInfo.getCreatedBy());
			bean.setCreatedDate(new Date());
			bean.setParentCode(groupInfo.getParentCode());
			
			// Call DAO layer to insert Database
			getGroupDAO().addTblGroup(bean);
		}

	}
	
	public void updateGroup(GroupInfo groupInfo) throws Exception {

		if (groupInfo != null) {

			// Declare bean object
			TblGroup bean = new TblGroup();
			bean.setGroupCode(groupInfo.getGroupCode());
			bean.setGroupName(groupInfo.getGroupName());
			bean.setUpdatedBy(groupInfo.getCreatedBy());
			bean.setUpdatedDate(new Date());

			// Call DAO layer to insert Database
			getGroupDAO().updateGroup(bean);
		}

	}
	
	public void deleteGroup(String groupCode) throws Exception {

		if (StringUtils.isNotBlank(groupCode)) {
			// Call DAO layer to insert Database
			getGroupDAO().deleteGroup(groupCode);
		}
	}
	
	public GroupInfo getGroup(String groupCode) throws Exception { 
		  
		GroupInfo groupInfo = null; 

		TblGroup tblGroup = getGroupDAO().getGroupByCode(groupCode);

		if (tblGroup != null) {
			groupInfo = new GroupInfo();
			BeanUtils.copyProperties(tblGroup, groupInfo);
		}
		return groupInfo;
	}
	
	public boolean checkLastGroup(String groupCode) throws Exception {
		boolean res = false;
		
		TblGroup tblGroup = getGroupDAO().getGroupByCode(groupCode);
		if (tblGroup != null && 
				(tblGroup.getParentCode() == null || Constants.GROUP_ASTRO_ADMIN.equals(tblGroup.getParentCode()))) {
			res = false; 
		} else {
			res = true;
		}
		
		return res;
	}
	
	public void deleteGroupAccount(Long groupAccountId) throws Exception {

		if (groupAccountId != null) {
			// Call DAO layer to insert Database
			getGroupAccountDAO().deleteGroupAccount(groupAccountId);
		}
	}
}